Introduction des données

On voit que les deux premières colonnes (X & id) sont inutiles pour nos analyses, on va donc les supprimer.

data <- read.csv("data/train.csv") 
# On supprime les lignes ou il y a des valeurs manquantes
data <- data[!rowMeans(is.na(data)*1) > 0,] 
str(data)
## 'data.frame':    103594 obs. of  25 variables:
##  $ X                                : int  0 1 2 3 4 5 6 7 8 9 ...
##  $ id                               : int  70172 5047 110028 24026 119299 111157 82113 96462 79485 65725 ...
##  $ Gender                           : chr  "Male" "Male" "Female" "Female" ...
##  $ Customer.Type                    : chr  "Loyal Customer" "disloyal Customer" "Loyal Customer" "Loyal Customer" ...
##  $ Age                              : int  13 25 26 25 61 26 47 52 41 20 ...
##  $ Type.of.Travel                   : chr  "Personal Travel" "Business travel" "Business travel" "Business travel" ...
##  $ Class                            : chr  "Eco Plus" "Business" "Business" "Business" ...
##  $ Flight.Distance                  : int  460 235 1142 562 214 1180 1276 2035 853 1061 ...
##  $ Inflight.wifi.service            : int  3 3 2 2 3 3 2 4 1 3 ...
##  $ Departure.Arrival.time.convenient: int  4 2 2 5 3 4 4 3 2 3 ...
##  $ Ease.of.Online.booking           : int  3 3 2 5 3 2 2 4 2 3 ...
##  $ Gate.location                    : int  1 3 2 5 3 1 3 4 2 4 ...
##  $ Food.and.drink                   : int  5 1 5 2 4 1 2 5 4 2 ...
##  $ Online.boarding                  : int  3 3 5 2 5 2 2 5 3 3 ...
##  $ Seat.comfort                     : int  5 1 5 2 5 1 2 5 3 3 ...
##  $ Inflight.entertainment           : int  5 1 5 2 3 1 2 5 1 2 ...
##  $ On.board.service                 : int  4 1 4 2 3 3 3 5 1 2 ...
##  $ Leg.room.service                 : int  3 5 3 5 4 4 3 5 2 3 ...
##  $ Baggage.handling                 : int  4 3 4 3 4 4 4 5 1 4 ...
##  $ Checkin.service                  : int  4 1 4 1 3 4 3 4 4 4 ...
##  $ Inflight.service                 : int  5 4 4 4 3 4 5 5 1 3 ...
##  $ Cleanliness                      : int  5 1 5 2 3 1 2 4 2 2 ...
##  $ Departure.Delay.in.Minutes       : int  25 1 0 11 0 0 9 4 0 0 ...
##  $ Arrival.Delay.in.Minutes         : num  18 6 0 9 0 0 23 0 0 0 ...
##  $ satisfaction                     : chr  "neutral or dissatisfied" "neutral or dissatisfied" "satisfied" "neutral or dissatisfied" ...
# On retire les colonnes inutiles
data <- data[,c(-1,-2)]
# On garde les 5000 premieres lignes
data <- data[1:5000,]
# On modifie les noms des lignes pour le style ;-)
row.names(data) <- paste("n°", sep="", 1:dim(data)[1]) 
# On renomme les colonnes pour avoir des noms moins longs (Utile pour l'affichage)
colnames(data) <- c("Genre", "Fidélité", "Age", "Type.du.vol", "Classe", "Distance", "Wifi", "Horaire.pratique", "Facilité.resevation", "Emplacement.porte", "Nourriture", "Enregistrement.en.ligne", "Siege.confort", "Loisir", "On.board.service", "Espace.jambe", "Gestion.bagage", "Checkin.service", "Inflight.service", "Propreté", "Retard.depart", "Retard.arrivé", "Satisfaction")
Petit avant gout des données :

Les notes sont assez homogènes, elles ont toutes :

##       Wifi       Horaire.pratique Facilité.resevation Emplacement.porte
##  Min.   :0.000   Min.   :0.00     Min.   :0.000       Min.   :1.000    
##  1st Qu.:2.000   1st Qu.:2.00     1st Qu.:2.000       1st Qu.:2.000    
##  Median :3.000   Median :3.00     Median :3.000       Median :3.000    
##  Mean   :2.742   Mean   :3.03     Mean   :2.766       Mean   :2.971    
##  3rd Qu.:4.000   3rd Qu.:4.00     3rd Qu.:4.000       3rd Qu.:4.000    
##  Max.   :5.000   Max.   :5.00     Max.   :5.000       Max.   :5.000    
##    Nourriture    Enregistrement.en.ligne Siege.confort       Loisir     
##  Min.   :0.000   Min.   :0.000           Min.   :1.000   Min.   :0.000  
##  1st Qu.:2.000   1st Qu.:2.000           1st Qu.:2.000   1st Qu.:2.000  
##  Median :3.000   Median :3.000           Median :4.000   Median :4.000  
##  Mean   :3.218   Mean   :3.251           Mean   :3.422   Mean   :3.338  
##  3rd Qu.:4.000   3rd Qu.:4.000           3rd Qu.:5.000   3rd Qu.:4.000  
##  Max.   :5.000   Max.   :5.000           Max.   :5.000   Max.   :5.000  
##  On.board.service  Espace.jambe   Gestion.bagage  Checkin.service
##  Min.   :0.00     Min.   :0.000   Min.   :1.000   Min.   :1.000  
##  1st Qu.:2.00     1st Qu.:2.000   1st Qu.:3.000   1st Qu.:3.000  
##  Median :4.00     Median :4.000   Median :4.000   Median :3.000  
##  Mean   :3.36     Mean   :3.338   Mean   :3.622   Mean   :3.318  
##  3rd Qu.:4.00     3rd Qu.:4.000   3rd Qu.:5.000   3rd Qu.:4.000  
##  Max.   :5.00     Max.   :5.000   Max.   :5.000   Max.   :5.000  
##  Inflight.service    Propreté    
##  Min.   :0.000    Min.   :1.000  
##  1st Qu.:3.000    1st Qu.:2.000  
##  Median :4.000    Median :3.000  
##  Mean   :3.653    Mean   :3.267  
##  3rd Qu.:5.000    3rd Qu.:4.000  
##  Max.   :5.000    Max.   :5.000

On peut aussi observer les autres variables quantitatives :

Analyse des données

ACP

On récupère toutes les données quantitatives et la satisfaction.

On ne prend que les 5000 premières lignes car le data set est trop gros (+100 000 lignes)

# On récupère Âge/Distance du vol/Retard Depart/Retard Arrivé (colonne 3/6/21/22), les notes (colonnes 7 à 20) et la satisfaction (colonne 23)
data_bis <- data[,c(3,6,21,22,7:20,23)]
res <- PCA(data_bis, quanti.sup=1:4, quali.sup=19, graph=FALSE)

Lors d’une ACP les individus ou variables peuvent être proches dans le plan mais eloignés dans l’espace s’ils sont mal représentés dans le plan. Ainsi, il est important d’expliquer les individus avec des variables bien representées dans le plan.

Pour cela on veillera à ne pas prendre les variables et individus ayant un cos2 trop bas. Ici on choisit un cos2 égale à 0.58 (qui n’est pas si haut au que ca en effet) afin d’avoir au moins 4 variables à utiliser, on pourra donc expliquer nos individus sur les axes 1 et 2 correctement.

Ici l’axe 1 va opposer le confort à bord (à droite) et l’inconfort (à gauche), tandis que l’axe 2 fera le contraste entre les aspects techniques en ce qui concerne le vol.

Les variables quantitatives supplémentaires ne sont pas du tout interprétables.

plot(res,select="cos2 0.58", choix="varcor")

Ci-dessous, on peut voir une nette séparation entre les individus satisfaits et insatisfaits/neutre. Les individus satisfaits sont ceux s’étant amusé et ayant trouvé l’avion propre (on les retrouve à droite sur le graph). À l’inverse les individus insatisfaits/neutre ont octroyé des notes plus basses concernant la propreté et les loisirs (on les retrouve à gauche sur le graph). On ne peut pas vraiment dire pour l’instant si la facilité de réservation et le wifi à bord influent sur la satisfaction du passager, en effet on ne retrouve pas de séparation entre les individus satisfaits et insatisfaits par rapport à l’axe 2.

Ici par exemple l’individu n°3122 est satisfait, or il a mal noté les loisirs, la propreté, le wifi et la facilité de réservation.

Sa satisfaction est probablement influencé par d’autres variables, qui sont qualitatives. On se penchera sur ce sujet lors de l’ACM.

plot(res,habillage=19, select="cos2 0.58", choix="ind",cex = 0.6)

L’individu qui contribue le plus à l’axe 1 y contribue à 0.15%.

max(res$ind$contrib[,1])
## [1] 0.1525821

Il y a 40 individus qui y contribuent pour plus de 0.1%

sum((res$ind$contrib[,1] > 0.1)*1)
## [1] 40

On n’a pas d’individus atypiques, ce qui est normal car nos données sont des notes entre 0 et 5 et on a vu qu’elles étaient assez homogènes


Les axes étant orthogonaux, les axes 1,2 et 3 prennent en compte 27.01% + 16.87% + 15.62% = 59.5%.

Ainsi avec le graphique ci-dessous on peut voir que les 3 premiers axes expliquent 59.5% de l’inertie sur les données. On peut s’en contenter, car avec une composante en plus, on ne gagne que très peu d’information pour la complexité d’exploitation des données que ça représente.

L’axe 2 et 3 expliquent à peu près autant l’un que l’autre l’inertie, ainsi on pourra visualiser les données projetées sur le plan formé par les axes 1,2 et 1,3 (On pourra aussi tester de visualiser les données projetés sur le plan formé par les axes 2,3).

On a un nouveau cercle de corrélation, ici on voit que :

  • Le confort des sièges, la nourriture et la propreté sont fortement corrélés
  • La gestion des bagages et les services proposés sont fortement corrélés
  • Dans ce plan les loisirs sont presque totalement expliqués par l’axe 1
  • L’axe 3 oppose le “confort” aux services qui sont faiblement corrélés dû à l’angle proche de 90 degrés
plot(res, select="cos2 0.58", choix="varcor", axes = c(1,3))

Avec le graph des individus ci-dessous, on peut voir que les passagers sont en général plus satisfaits Avec le graph des individus ci-dessous, on peut voir que :

  • Les loisirs à bord
  • Un service (Gestion bagage, Inflight.service, On.board.service) de qualité
  • Le confort lors du trajet (Siege.confort, nourriture, propreté)

influent sur la satisfaction du client positivement.

Inversement pour les passagers non satisfaits/neutres.

plot(res, habillage=19, select="cos2 0.58", choix="ind", axes = c(1,3))

Ci-dessous on a le cercle de corrélation avec l’axe 2 et 3:

plot(res, select="cos2 0.6", choix="varcor", axes = c(2,3))

Il n’y a pas grand-chose à interpréter car le barycentre des voyageurs satisfaits et non satisfaits sont tout les 2 proches du centre de gravité de ce plan.

plot(res, invisible="ind",choix="ind", axes = c(2,3))

Transformations & double centrage

Certains passagers ont attribué comme notes 0 pour certaines catégories du vol, on décide de ne pas faire de transformation par l’inverse car \(\frac{1}{0}\) est un quotient indéterminé.

Log-transformation

On effectue la transformation ”double centrage” sur les données log-transformées afin de voir si on peut faire gagner en contribution les premières composantes afin d’être plus précis lors de nos analyses.

data_bis2 <- log(data_bis[,c(-4:-1,-19)])
data_bis2 <- t(scale(t(data_bis2)))
res2 <- PCA(data_bis2, graph=FALSE)
## Warning in PCA(data_bis2, graph = FALSE): Missing values are imputed by the mean
## of the variable: you should use the imputePCA function of the missMDA package
barplot(res2$eig[,2], col=rainbow(n=14,alpha=0.6,start=0.33,end=0.66),main="Pourcentage d'intertie expliquée par chaque axe\n(Données log-transformées) ", ylab="Contribution en %")
lines(seq(0.75,16.3,(16.3-0.75)/13),res2$eig[,2],type="b")
text(seq(0.75,16.3,(16.3-0.75)/13),res2$eig[,2]-1, paste(round(res2$eig[,2],2),"%"), cex=0.7)

Transformation par racines carrée

On effectue la transformation ”double centrage” sur les données transformées par racine carrée afin de voir si on peut faire gagner en contribution les premières composantes afin d’être plus précis lors de nos analyses.

data_bis3 <- sqrt(data_bis[,c(-4:-1,-19)])
data_bis3 <- t(scale(t(data_bis3)))
res3 <- PCA(data_bis3, graph=FALSE)
barplot(res3$eig[,2], col=rainbow(n=14,alpha=0.6,start=0.66,end=1),main="Pourcentage d'intertie expliquée par chaque axe\n(Données transformées par racine carrée)", ylab="Contribution en %")
lines(seq(0.75,16.3,(16.3-0.75)/13),res3$eig[,2],type="b")
text(seq(0.75,16.3,(16.3-0.75)/13),res3$eig[,2]-1, paste(round(res3$eig[,2],2),"%"), cex=0.7)

Les transformations nous font perde de l’information pour le premier axe, on en gagne pour le deuxième. Le reste de l’inertie se répartie au niveau de l’axe 3 à 13. On préfère donc garder une ACP sur les données non transformées, ni double centrées car on avait plus d’inforation sur les 3 premiers axes.

Conclusion ACP

Ici on a pu étudier l’impact des notes accordées par les clients (variables quantitatives) sur leur satisfaction concernant le trajet.

Il en est ressorti que les services proposés dans l’avion et le confort à bord sont des aspects primordiaux pour la satisfaction des voyageurs.

ACM

Intéressons nous maintenant à savoir si le “profil” des clients (données qualitatives) influe sur leur satisfaction.

On donnes ci-dessous le tableau des variables qualitatives que nous allons étudier :

res.mca <-MCA(data_bis, quali.sup = 5, graph=FALSE)

On peut observer que la première dimension influe à un peu plus de 30%, quant à la 2, 3, 4 elles influent toutes autour de 20%.

Il sera donc surement nécessaire de s’intéresser à ces 4 dimensions.

Voici ci-dessous les cos2 de nos modalités sur chacun des 4 premiers axes.

En se référent aux cos2 des barplots précédents , on interprete ceux qui ont un cos2>0.7 sur le plan formé par les axes 1 et 2.

L’axe 1 oppose les passagers qui voyagent pour le business et les passagers qui voyagent pour un motif personnel. Ceux qui voyagent pour le travail sont en général plus satisfaits que ceux qui voyagent pour un motif personnel.

L’axe 2 oppose les passagers loyaux aux non loyaux, il en résulte que les passagers non loyaux sont plus souvent insatisfaits que les passagers loyaux.

Les deux axes prennent aussi en compte à eux deux les voyageurs en classe business et éco. On peut voir que les voyageurs en classe éco sont plus souvent insatisfait de leur voyage que ceux en business classe.

plot(res.mca, invisible="ind", axes=c(1,2))

En se referent aux cos2 (cos2 > 0.7) pour l’axe 3 des barplots précédents :

On peut voir que l’axe 3 oppose les personnes de sexe different, on ne peut pas dire grand-chose quant à l’influence sur la satisfaction du client, on pourrait peut-être dire que les femmes sont un peu moins satisfaites mais c’est à vérifier.

plot(res.mca, invisible="ind", axes=c(1,3))

En vérifiant on peut donc voir que les voyageuses sont un petit peu moins souvent satisfaites que les voyageurs.

##         
##          neutral or dissatisfied satisfied
##   Female               0.5729412 0.4270588
##   Male                 0.5559184 0.4440816

Pour prendre en compte les voyageurs classe éco plus on visualise sur le plan formé par l’axe 3 et 4

On peut voir ici que les voyageurs en classe Éco Plus sont moins satisfaits de leur voyages, ils sont très excentrés car ils représentes des données inhabituelles.

plot(res.mca, invisible="ind", axes=c(3,4))

### Conclusion

D’après l’ACM :

  • Si un passager voyage pour des raisons personnelles, il a moins de chance d’être satisfait du vol qu’un passager qui voyage pour le business.

  • Si le passager est un client fidèle (Loyal custommer) il a plus de chance d’être satisfait du vol qu’un passager qui est déloyal (Disloyal custommer).

  • Si un voyageur est en classe business, cela influera positivement sur sa satisfaction, alors que s’il est en classe Eco cela influera négativement. Les passagers Éco plus sont particuliers, mais le fait d’être en classe Éco plus influe négativement sur leur satisfaction.

  • Le sexe de l’individu n’a pas l’air d’influer significativement sur la satisfaction, mais on peut faire l’hypothèse que les femmes sont moins satisfaites que les hommes.

Anova

Nous allons à présent nous pencher sur la corrélation entre les différentes variables. En observant

data_bis = data[,7:20]
mean_notes <-rowMeans(data_bis)

data[1:20,23]
##  [1] "neutral or dissatisfied" "neutral or dissatisfied"
##  [3] "satisfied"               "neutral or dissatisfied"
##  [5] "satisfied"               "neutral or dissatisfied"
##  [7] "neutral or dissatisfied" "satisfied"              
##  [9] "neutral or dissatisfied" "neutral or dissatisfied"
## [11] "neutral or dissatisfied" "neutral or dissatisfied"
## [13] "neutral or dissatisfied" "satisfied"              
## [15] "neutral or dissatisfied" "neutral or dissatisfied"
## [17] "satisfied"               "satisfied"              
## [19] "satisfied"               "neutral or dissatisfied"
plot(mean_notes[1:20])

boxplot( data_bis$Nourriture ~ data_bis$Gestion.bagage)
points(tapply(data_bis$Nourriture, data_bis$Gestion.bagage ,mean), col = 'red')

res = lm(formula =  data_bis$Wifi ~ data_bis$Propreté)
summary(res)
## 
## Call:
## lm(formula = data_bis$Wifi ~ data_bis$Propreté)
## 
## Residuals:
##     Min      1Q  Median      3Q     Max 
## -2.9594 -0.8337  0.1663  1.1663  2.5434 
## 
## Coefficients:
##                   Estimate Std. Error t value Pr(>|t|)    
## (Intercept)        2.33092    0.04985  46.762   <2e-16 ***
## data_bis$Propreté  0.12571    0.01415   8.885   <2e-16 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 1.319 on 4998 degrees of freedom
## Multiple R-squared:  0.01555,    Adjusted R-squared:  0.01535 
## F-statistic: 78.94 on 1 and 4998 DF,  p-value: < 2.2e-16
anova(res)
## Analysis of Variance Table
## 
## Response: data_bis$Wifi
##                     Df Sum Sq Mean Sq F value    Pr(>F)    
## data_bis$Propreté    1  137.4  137.39  78.941 < 2.2e-16 ***
## Residuals         4998 8698.8    1.74                      
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1